package org.easylookandfeel.core;

import java.awt.Component;
import java.util.Arrays;
import java.util.List;

import org.easylookandfeel.adapter.LookAndFeelAdapter;

/**
 * Facade of EasyLookAndFeel component.
 * 
 * @author pcmnac@gmail.com
 * 
 */
public class EasyLookAndFeel {

  /**
   * Initializes look and feel management using a single
   * {@link LookAndFeelAdapter}.
   * 
   * @param rootComponent
   *          The root component where look and feel changes will be applied to.
   * @param adapter
   *          A {@link LookAndFeelAdapter} to handles look and feel processing.
   * @param useSystemLookAndFeel
   *          Indicates if system look and feel should be loaded as default.
   * 
   * @return A new {@link LookAndFeelManager} object. It can be used to
   *         add/remove {@link LookAndFeelAdapter}s dynamically or to reload
   *         available looks from system.
   */
  public static LookAndFeelManager start(Component rootComponent,
      LookAndFeelAdapter adapter, boolean useSystemLookAndFeel) {
    return start(rootComponent,
        (adapter != null ? new LookAndFeelAdapter[] { adapter } : null),
        useSystemLookAndFeel);
  }

  /**
   * Initializes look and feel management using a single
   * {@link LookAndFeelAdapter}. Using this method, system look and feel will
   * be loaded as default.
   * 
   * @param rootComponent
   *          The root component where look and feel changes will be applied to.
   * @param adapter
   *          A {@link LookAndFeelAdapter} to handles look and feel processing.
   * 
   * @return A new {@link LookAndFeelManager} object. It can be used to
   *         add/remove {@link LookAndFeelAdapter}s dynamically or to reload
   *         available looks from system.
   */
  public static LookAndFeelManager start(Component rootComponent,
      LookAndFeelAdapter adapter) {
    return start(rootComponent, adapter, true);
  }

  /**
   * Initializes look and feel management using multiple
   * {@link LookAndFeelAdapter}s.
   * 
   * @param rootComponent
   *          The root component where look and feel changes will be applied to.
   * @param adapters
   *          The {@link LookAndFeelAdapter}s array to handle look and feel
   *          processing.
   * @param useSystemLookAndFeel
   *          Indicates if system look and feel should be loaded as default.
   * 
   * @return A new {@link LookAndFeelManager} object. It can be used to
   *         add/remove {@link LookAndFeelAdapter}s dynamically or to reload
   *         available looks from system.
   */
  public static LookAndFeelManager start(Component rootComponent,
      LookAndFeelAdapter[] adapters, boolean useSystemLookAndFeel) {
    return start(rootComponent, (adapters != null ? Arrays.asList(adapters)
        : null), useSystemLookAndFeel);
  }

  /**
   * Initializes look and feel management using multiple
   * {@link LookAndFeelAdapter}s. Using this method, system look and feel will
   * be loaded as default.
   * 
   * @param rootComponent
   *          The root component where look and feel changes will be applied to.
   * @param adapters
   *          The {@link LookAndFeelAdapter}s array to handle look and feel
   *          processing.
   * 
   * @return A new {@link LookAndFeelManager} object. It can be used to
   *         add/remove {@link LookAndFeelAdapter}s dynamically or to reload
   *         available looks from system.
   */
  public static LookAndFeelManager start(Component rootComponent,
      LookAndFeelAdapter[] adapters) {
    return start(rootComponent, adapters, true);
  }

  /**
   * Initializes look and feel management using multiple
   * {@link LookAndFeelAdapter}s.
   * 
   * @param rootComponent
   *          The root component where look and feel changes will be applied to.
   * @param adapters
   *          The {@link LookAndFeelAdapter}s list to handle look and feel
   *          processing.
   * @param useSystemLookAndFeel
   *          Indicates if system look and feel should be loaded as default.
   * 
   * @return A new {@link LookAndFeelManager} object. It can be used to
   *         add/remove {@link LookAndFeelAdapter}s dynamically or to reload
   *         available looks from system.
   */
  public static LookAndFeelManager start(Component rootComponent,
      List<LookAndFeelAdapter> adapters, boolean useSystemLookAndFeel) {

    // Creates a new LookAndFeelManager object.
    LookAndFeelManager manager = new LookAndFeelManager(rootComponent,
        useSystemLookAndFeel);

    // Adds adapters to manager.
    if (adapters != null) {
      for (LookAndFeelAdapter adapter : adapters) {
        manager.addAdapter(adapter);
      }
    }

    // Initializes look-and-feel management.
    manager.initialize();

    // Returns the newly created manager.
    return manager;
  }

  /**
   * Initializes look and feel management using multiple
   * {@link LookAndFeelAdapter}s. Using this method, system look and feel will
   * be loaded as default.
   * 
   * @param rootComponent
   *          The root component where look and feel changes will be applied to.
   * @param adapters
   *          The {@link LookAndFeelAdapter}s list to handle look and feel
   *          processing.
   * 
   * @return A new {@link LookAndFeelManager} object. It can be used to
   *         add/remove {@link LookAndFeelAdapter}s dynamically, or to reload
   *         available looks from system.
   */
  public static LookAndFeelManager start(Component rootComponent,
      List<LookAndFeelAdapter> adapters) {
    return start(rootComponent, adapters, true);
  }

  /**
   * Initializes look and feel management using no {@link LookAndFeelAdapter}s.
   * Using this method, system look and feel will be loaded as default.
   * 
   * @param rootComponent
   *          The root component where look and feel changes will be applied to.
   * 
   * @return A new {@link LookAndFeelManager} object. It can be used to
   *         add/remove {@link LookAndFeelAdapter}s dynamically or to reload
   *         available looks from system.
   */
  public static LookAndFeelManager start(Component rootComponent) {
    return start(rootComponent, (List<LookAndFeelAdapter>) null);
  }

}
